package org.yaac.server.egql;

import static com.google.common.collect.Sets.newHashSet;

import java.io.Serializable;
import java.util.Map;
import java.util.Set;

import org.yaac.server.egql.evaluator.AggregationEvaluator;
import org.yaac.server.egql.evaluator.aggregator.Aggregator;

import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;

/**
 * 
 * intermediate status when executing select statement
 * 
 * RecordContext focused on single entity record, 
 * while this context mainly focuses on a global vairables
 * 
 * @author Max Zhu (thebbsky@gmail.com)
 *
 */
// TODO : title namespace
public class StatementContext implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * client id used by channel service to push results back to clients 
	 */
	private String clientId;

	private Integer batchSize;

	/**
	 * remaining max result
	 */
	private Integer maxResult;

	private String startCursor; 
	
	/**
	 * groupByRecords, it's a super set of row record in groupByTable, 
	 * 
	 * because it is not necessary to have aggregator when using group by functions
	 */
	private Set<Map<EntityProperty, Object>> groupByRecords;
	
	private Table<Map<EntityProperty, Object>, AggregationEvaluator, Aggregator> groupByTable;
	
	public String getClientId() {
		return clientId;
	}

	public void setClientId(String clientId) {
		this.clientId = clientId;
	}

	public Integer getBatchSize() {
		return batchSize;
	}

	public void setBatchSize(Integer batchSize) {
		this.batchSize = batchSize;
	}

	public Integer getMaxResult() {
		return maxResult;
	}

	public void setMaxResult(Integer maxResult) {
		this.maxResult = maxResult;
	}

	public String getStartCursor() {
		return startCursor;
	}

	public void setStartCursor(String startCursor) {
		this.startCursor = startCursor;
	}

	public Table<Map<EntityProperty, Object>, AggregationEvaluator, Aggregator> getGroupByTable() {
		if (groupByTable == null) {
			groupByTable = HashBasedTable.create();
		}
		
		return groupByTable;
	}
	
	public Set<Map<EntityProperty, Object>> getGroupByRecords() {
		if (groupByRecords == null) {
			groupByRecords = newHashSet();
		}
		
		return groupByRecords;
	}
	
	public boolean allowMoreResult() {
		return maxResult >= 0;
	}

	public void decreaseRemainingResultQuota() {
		this.maxResult --;
	}
}
 